package com.chezai.client.activitys;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.chezai.client.R;
import com.chezai.client.bean.EndSupplementPhotoResult;
import com.chezai.client.bean.RandomPhoto;
import com.chezai.client.bean.Speech;
import com.chezai.client.bean.TakePhotoEntity;
import com.chezai.client.dao.manager.RandomPhotoDaoManager;
import com.chezai.client.fragment.LearnCarFragment;
import com.chezai.client.global.Const;
import com.chezai.client.global.DeviceFactory;
import com.chezai.client.global.LogService;
import com.chezai.client.global.TerminalApplication;
import com.chezai.client.utils.AppManager;
import com.chezai.client.utils.CameraMgr;
import com.chezai.client.utils.SDCardUtil;
import com.chezai.client.utils.SpeechUtils;
import com.chezai.client.widget.FaceView;
import com.orhanobut.logger.Logger;

import org.greenrobot.eventbus.EventBus;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import butterknife.BindView;

import static com.chezai.client.R.id.faceView;


/**
 * 拍照页
 * Created by likunyang on 2017/8/31.
 */

public class CameraActivity extends BaseActivity implements Camera.ErrorCallback, Camera.PictureCallback, SurfaceHolder.Callback, Camera.FaceDetectionListener {

    @BindView(R.id.surfaceView)
    SurfaceView mSurfaceView;
    @BindView(faceView)
    FaceView mFaceView;
    @BindView(R.id.ll_content)
    RelativeLayout prContent;
    @BindView(R.id.tv_top)
    TextView tvTop;

    private SurfaceHolder mHolder;
    private Camera mCamera;
    private int mPhotoSizeType = 2;
    private int mWidth;
    private int mHeight;
    private boolean isCountDown; //是否为倒计时拍照
    private boolean isTest = false;//是否为调试
    private boolean mFaceDetectionRunning = false;
    private String photoPath;
    private int mCountDownTime;
    private int mPhotoEventType;
    private int trainPart;
    private String studentName = "";
    private String coachName = "";
    private boolean isStartPreview;//是否开始预览
    private boolean isTakePhoto;
    private int cameraChannel;
    private int[] cameraDisplayOrientation;
    private MainHandler mMainHandler;
    private CountDownTimer countDownTimer;
    private long mClassRecordId;
    private boolean isSpeek;
    private boolean isSpeeking;//正在播放语音
    private long mRandomPhotoId = -1;
    private RandomPhoto mRandomPhoto;
    private boolean mIsEndSupplementPhoto;

    /**
     * @param from
     * @param takePhotoMode        拍照模式
     * @param countDownTime        倒计时时间
     * @param photoEventType       拍照类型
     * @param trainPart            培训部分
     * @param studentName          学员名字
     * @param coachName            教练名字
     * @param cameraChannel        拍照通道
     * @param classRecordId        课堂记录ID
     * @param randomPhotoId        抓拍照片记录ID
     * @param isEndSupplementPhoto 是否为结束教学补拍照片
     */
    public static void startCameraActivity(Activity from, int takePhotoMode, int countDownTime
            , int photoEventType, int trainPart, String studentName, String coachName
            , int cameraChannel, Long classRecordId, Long randomPhotoId, boolean isEndSupplementPhoto) {
        if (AppManager.getAppManager().isOpenActivity(CameraActivity.class)) return;
        Const.isTakePhoto = true;
        Intent intent = new Intent(from, CameraActivity.class);
        intent.putExtra(Const.TAKE_PHOTO_MODE, takePhotoMode);
        intent.putExtra(Const.COUNT_DOWN_TIME, countDownTime);
        intent.putExtra(Const.EVENT_PHOTO_TYPE, photoEventType);
        intent.putExtra(Const.CAMERA_CHANNEL, cameraChannel);
        intent.putExtra(Const.TRAIN_PART, trainPart);
        intent.putExtra(Const.IS_END_SUPPLEMENT_PHOTO, isEndSupplementPhoto);
        if (!TextUtils.isEmpty(studentName)) {
            intent.putExtra(Const.STUDENT_NAME, studentName);
        }
        if (!TextUtils.isEmpty(coachName)) {
            intent.putExtra(Const.COACH_NAME, coachName);
        }
        if (classRecordId != null) {
            intent.putExtra(Const.CLASS_RECORD_ID, classRecordId);
        }
        if (randomPhotoId != null) {
            intent.putExtra(Const.RANDOM_PHOTO_ID, randomPhotoId);
        }

        from.startActivity(intent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Const.isTakePhoto = false;
    }

    @Override
    public int getLayoutId() {
        return R.layout.activity_camera;
    }

    @Override
    public void initView(Bundle savedInstanceState) {
        mMainHandler = new MainHandler();
    }

    @Override
    public void initData() {
        Intent intent = getIntent();
        int takePhotoMode = intent.getIntExtra(Const.TAKE_PHOTO_MODE, Const.TakePhotoMode.COUNT_DOWN_TIME);
        cameraChannel = intent.getIntExtra(Const.CAMERA_CHANNEL, 1);
        isTest = takePhotoMode == Const.TakePhotoMode.TEST_CAMERA;
        if (isTest) {
            tvTop.setText("调试摄像头");
            isCountDown = false;
        } else {
            isCountDown = takePhotoMode == Const.TakePhotoMode.COUNT_DOWN_TIME;
            mCountDownTime = intent.getIntExtra(Const.COUNT_DOWN_TIME, 10);
            mPhotoEventType = intent.getIntExtra(Const.EVENT_PHOTO_TYPE, 0);
            trainPart = intent.getIntExtra(Const.TRAIN_PART, 0);
            mIsEndSupplementPhoto = intent.getBooleanExtra(Const.IS_END_SUPPLEMENT_PHOTO, false);
            if (intent.hasExtra(Const.STUDENT_NAME)) {
                studentName = intent.getStringExtra(Const.STUDENT_NAME);
            }
            if (intent.hasExtra(Const.COACH_NAME)) {
                coachName = intent.getStringExtra(Const.COACH_NAME);
            }
            if (intent.hasExtra(Const.CLASS_RECORD_ID)) {
                mClassRecordId = intent.getLongExtra(Const.CLASS_RECORD_ID, -1);
            }
            if (intent.hasExtra(Const.RANDOM_PHOTO_ID)) {
                mRandomPhotoId = intent.getLongExtra(Const.RANDOM_PHOTO_ID, -1);
                if (mRandomPhotoId != -1) {
                    mRandomPhoto = RandomPhotoDaoManager.getInstance().findPeriodRecordPhoto(mRandomPhotoId);
                }
            }
            if (mPhotoEventType == Const.PhotoEventType.ZHUAPAI || mPhotoEventType == Const.PhotoEventType.TEACHE_SIGN_IN ||
                    mPhotoEventType == Const.PhotoEventType.TEACHE_SIGN_OUT) {
                photoPath = SDCardUtil.getCoachPhotoPath();
            } else {
                if (mRandomPhoto != null) {
                    photoPath = SDCardUtil.getStudentPhotoPath(mRandomPhoto.getTakePhotoTimeStamp());
                } else {
                    photoPath = SDCardUtil.getStudentPhotoPath();
                }
            }
            switch (mPhotoEventType) {
                case Const.PhotoEventType.TEACHE_SIGN_OUT:
                case Const.PhotoEventType.STUDENT_SIGN_OUT:
                    tvTop.setText("签退拍照");
                    break;
                case Const.PhotoEventType.TEACHE_SIGN_IN:
                case Const.PhotoEventType.STUDENT_SIGN_IN:
                    tvTop.setText("签到拍照");
                    break;
                case Const.PhotoEventType.STUDENT_FACE_LOGIN:
                    tvTop.setText("人脸检测拍照");
                    break;
                case Const.PhotoEventType.ZHUAPAI:
                case Const.PhotoEventType.STUDENT_LEARNING:
                    tvTop.setText("抓拍");
                    break;
            }
            if (!mIsEndSupplementPhoto) {
                isSpeek = ((trainPart == Const.TrainPart.TWO || trainPart == Const.TrainPart.THREE) && mPhotoEventType == Const.PhotoEventType.STUDENT_LEARNING);
                setUpPreview(mPhotoEventType == Const.PhotoEventType.ZHUAPAI || trainPart == Const.TrainPart.THREE);
            }
        }
        try {
            cameraDisplayOrientation = CameraMgr.setCameraDisplayOrientation(this, cameraChannel);
            mFaceView.isMirror(cameraChannel);
            mFaceView.setDisplayOrientation(cameraDisplayOrientation[1]);
            getPhotoSize();
            mHolder = mSurfaceView.getHolder();
            mHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半透明 transparent透明
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            mHolder.addCallback(this);
        } catch (Exception e) {
            showToast(e.getMessage());
            TakePhotoEntity takePhoto = new TakePhotoEntity();
            takePhoto.classRecordId = mClassRecordId;
            takePhoto.status = TakePhotoEntity.TAKE_PHOTO_FAILE;
            if (mPhotoEventType == Const.PhotoEventType.STUDENT_LEARNING) {
                LogService.getInstance(TerminalApplication.mContext).sendLog("take student learning photo ,camera init failed ! ");
            }
            EventBus.getDefault().postSticky(takePhoto);
            finish();
        }
    }


    /**
     * 设置视图显示区域大小
     *
     * @param isSnapshot 是否为抓拍
     */
    private void setUpPreview(boolean isSnapshot) {
        if (!isSnapshot) {
            isCountDown = true;
            mCountDownTime = 3;
        }
        if (isSnapshot) {
            tvTop.setVisibility(View.GONE);
            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) prContent.getLayoutParams();
            params.height = 1;
            params.width = 1;
            prContent.setLayoutParams(params);
            RelativeLayout.LayoutParams perParams = (RelativeLayout.LayoutParams) mSurfaceView.getLayoutParams();
            perParams.height = 1;
            perParams.width = 1;
            mSurfaceView.setLayoutParams(perParams);
        }
    }


    @Override
    public void onError(int error, Camera camera) {
        showToast("摄像头启动失败，请重试！");
        LogService.getInstance(TerminalApplication.mContext).sendLog("take photo ,camera start failed! " + error);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            mCamera = Camera.open(cameraChannel);
            mCamera.setErrorCallback(this);
        } catch (RuntimeException e) {
            showToast("摄像头启动失败，请重试2！");
            LogService.getInstance(TerminalApplication.mContext).sendLog("take photo ,camera start failed! " + e.getMessage());
            finish();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setPictureFormat(PixelFormat.JPEG);
            List<Camera.Size> pictures = parameters.getSupportedPreviewSizes();
            Camera.Size optionSize = CameraMgr.getOptimalPreviewSize(pictures, mSurfaceView.getWidth(), mSurfaceView.getHeight());
            parameters.setPreviewSize(optionSize.width, optionSize.height);// 设置预览照片的大小
            parameters.setPictureSize(mWidth, mHeight);
            List<String> focusModes = parameters.getSupportedFocusModes();
            if (focusModes.contains("continuous-video")) {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            }
            if (parameters.isAutoExposureLockSupported()) {
                parameters.setAutoExposureLock(false);
            }
            if (parameters.isAutoWhiteBalanceLockSupported()) {
                String whiteBalance = parameters.getWhiteBalance();
                if (!TextUtils.equals(Camera.Parameters.WHITE_BALANCE_AUTO, whiteBalance)) {
                    parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
                }
            }
            mCamera.setParameters(parameters);
            mCamera.setDisplayOrientation(cameraDisplayOrientation[1]);
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
            mMainHandler.sendEmptyMessageDelayed(Const.CAMERA_HAS_STARTED_PREVIEW, 1500);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        cameraRelease();
    }

    /**
     * 开始预览
     */
    private void startPreview() {
        if (isStartPreview) return;
        isStartPreview = true;
        if (isCountDown) {
            startCountDownTime();
        } else {
            /*
             * 1.支持人脸聚焦 并且不是倒计时拍照，则等对焦成功自动拍照
             * 2.不支持人脸，直接倒计时mCountDownTime秒拍照
             */
            if (mCamera != null && mCamera.getParameters().getMaxNumDetectedFaces() > 0) {
                startFaceDetection();
            } else {
                startCountDownTime();
            }
        }
    }

    @Override
    public void onFaceDetection(Camera.Face[] faces, Camera camera) {
        if (mFaceView != null) mFaceView.setFaces(faces);
        if (isTest) return;
        if (faces.length > 0 && !isTakePhoto) {
            isTakePhoto = true;
            mCountDownTime = 1;
            startCountDownTime();
        }
    }

    /**
     * 开始倒计时拍照
     */

    public void startCountDownTime() {
        if (isTest) return;
        countDownTimer = new CountDownTimer(mCountDownTime * 1000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                if (isSpeek && !isSpeeking) {
                    isSpeeking = true;
                    SpeechUtils.getInstance().playOrComposed(Speech.INVERTED_SECONDS.getMsg(), Speech.INVERTED_SECONDS.getFilePath());
                }
            }

            @Override
            public void onFinish() {
                takePicture();
            }
        };
        countDownTimer.start();
    }

    /**
     * 拍照
     */
    public void takePicture() {
        if (mCamera == null) return;
        Logger.t(TAG).i("开始拍照");
        stopCountDown();
        stopFaceDetection();
        try {
            mCamera.takePicture(null, null, this);
        } catch (RuntimeException e) {
            showToast("拍照失败！");
            TakePhotoEntity takePhoto = new TakePhotoEntity();
            takePhoto.classRecordId = mClassRecordId;
            takePhoto.status = TakePhotoEntity.TAKE_PHOTO_FAILE;
            EventBus.getDefault().postSticky(takePhoto);
            if (mPhotoEventType == Const.PhotoEventType.STUDENT_LEARNING) {
                LogService.getInstance(TerminalApplication.mContext).sendLog("take student learning photo ,take photo  failed ! " + e.getMessage());
            }
            finish();
        }
    }

    private void stopCountDown() {
        if (countDownTimer != null) {
            countDownTimer.cancel();
            countDownTimer = null;
        }
    }

    /**
     * 开始人脸检测
     */
    private void startFaceDetection() {
        if (mFaceView != null) {
            mFaceView.clearFaces();
            mFaceView.setVisibility(View.VISIBLE);
        }
        mCamera.setFaceDetectionListener(this);
        mCamera.startFaceDetection();
        mFaceDetectionRunning = true;
    }

    /**
     * 停止人脸检测
     */
    private void stopFaceDetection() {
        if (mFaceDetectionRunning) {
            mCamera.setFaceDetectionListener(null);
            mCamera.stopFaceDetection();
            mFaceView.clearFaces();
            mFaceDetectionRunning = false;
        }
    }

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        Bitmap bitmap = null;
        boolean isSucess = false;
        try {
            File file = new File(photoPath);
            if (file.exists()) {
                file.delete();
            }
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
            if (DeviceFactory.hardware.isNeedRotaingImage()) {
                bitmap = CameraMgr.rotaingImageView(180, bitmap);
            }
            long timeStamp = mRandomPhoto == null ? System.currentTimeMillis() : mRandomPhoto.getTakePhotoTimeStamp();
            bitmap = CameraMgr.onWaterDraw(bitmap, trainPart, studentName, coachName, timeStamp);
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
            int quality = 80;
            if (mPhotoSizeType == 2 || mPhotoSizeType == 4 || mPhotoSizeType == 7 || mPhotoSizeType == 8) {
                quality = 70;
            }
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);// 将图片压缩的流里面
            bos.flush();// 刷新此缓冲区的输出流
            bos.close();// 关闭此输出流并释放与此流有关的所有系统资源
            camera.stopPreview();// 关闭预览 处理数据
            bitmap.recycle();// 回收bitmap空间
            isSucess = true;
            if (isSpeek) {
                SpeechUtils.getInstance().playOrComposed(Speech.SNAPSHOT_SUCESS.getMsg(), Speech.SNAPSHOT_SUCESS.getFilePath());
            }
        } catch (IOException e) {
            e.printStackTrace();
            isSucess = false;
            if (mPhotoEventType == Const.PhotoEventType.STUDENT_LEARNING) {
                LogService.getInstance(TerminalApplication.mContext).sendLog("take student learning photo ,write photo  failed ! " + e.getMessage());
            }
        } finally {
//            LearnCarFragment fragment = new LearnCarFragment();
//            fragment.startPush();
            if (bitmap != null) {
                bitmap.recycle();
            }
            if (mIsEndSupplementPhoto) {
                if (isSucess) {
                    mRandomPhoto.setPhotoPath(photoPath);
                    mRandomPhoto.setUploadStatus(Const.UPLOAD_FAILED);
                    mRandomPhoto.setIsEndSupplementPhoto("supplement_photo");
                    RandomPhotoDaoManager.getInstance().update(mRandomPhoto);
                    EventBus.getDefault().postSticky(new EndSupplementPhotoResult(mRandomPhotoId));
                } else {
                    showToast("拍照失败，请重试!");
                }
            } else {
                TakePhotoEntity takePhoto = new TakePhotoEntity(isSucess ? TakePhotoEntity.TAKE_PHOTO_SUCESS : TakePhotoEntity.TAKE_PHOTO_FAILE, mRandomPhotoId, photoPath, mPhotoEventType, mClassRecordId);
                EventBus.getDefault().postSticky(takePhoto);
            }
        }
        finish();
    }

    private void cameraRelease() {
        if (null != mCamera) {
            stopFaceDetection();
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    /**
     * 获取拍照图片大小
     */
    public void getPhotoSize() {
        switch (mPhotoSizeType) {
            case 1:
                mWidth = 320;
                mHeight = 240;
                break;
            case 2:
                mWidth = 640;
                mHeight = 480;
                break;
            case 3:
                mWidth = 800;
                mHeight = 600;
                break;
            case 4:
                mWidth = 1024;
                mHeight = 768;
                break;
            case 5:
                mWidth = 176;
                mHeight = 144;
                break;
            case 6:
                mWidth = 352;
                mHeight = 288;
                break;
            case 7:
                mWidth = 704;
                mHeight = 288;
                break;
            case 8:
                mWidth = 704;
                mHeight = 576;
                break;
        }
    }

    private class MainHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Const.CAMERA_HAS_STARTED_PREVIEW:
                    startPreview();
                    break;
            }
            super.handleMessage(msg);
        }
    }
}
